(function(window,document,undefined){"use strict";if(window.PushStream){return;} var Utils={};var days=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];var months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];var valueToTwoDigits=function(value){return((value<10)?'0':'')+value;};Utils.dateToUTCString=function(date){var time=valueToTwoDigits(date.getUTCHours())+':'+valueToTwoDigits(date.getUTCMinutes())+':'+valueToTwoDigits(date.getUTCSeconds());return days[date.getUTCDay()]+', '+valueToTwoDigits(date.getUTCDate())+' '+months[date.getUTCMonth()]+' '+date.getUTCFullYear()+' '+time+' GMT';};var extend=function(){var object=arguments[0]||{};for(var i=0;i100){logElement.innerHTML=lines.slice(-100).join('\n');}}}};var Ajax={_getXHRObject:function(crossDomain){var xhr=false;if(crossDomain){try{xhr=new window.XDomainRequest();}catch(e){} if(xhr){return xhr;}} try{xhr=new window.XMLHttpRequest();} catch(e1){try{xhr=new window.ActiveXObject("Msxml2.XMLHTTP");} catch(e2){try{xhr=new window.ActiveXObject("Microsoft.XMLHTTP");} catch(e3){xhr=false;}}} return xhr;},_send:function(settings,post){settings=settings||{};settings.timeout=settings.timeout||30000;var xhr=Ajax._getXHRObject(settings.crossDomain);if(!xhr||!settings.url){return;} Ajax.clear(settings);settings.xhr=xhr;if(window.XDomainRequest&&(xhr instanceof window.XDomainRequest)){xhr.onload=function(){if(settings.afterReceive){settings.afterReceive(xhr);} if(settings.success){settings.success(xhr.responseText);}};xhr.onerror=xhr.ontimeout=function(){if(settings.afterReceive){settings.afterReceive(xhr);} if(settings.error){settings.error(xhr.status);}};}else{xhr.onreadystatechange=function(){if(xhr.readyState===4){Ajax.clear(settings);if(settings.afterReceive){settings.afterReceive(xhr);} if(xhr.status===200){if(settings.success){settings.success(xhr.responseText);}}else{if(settings.error){settings.error(xhr.status);}}}};} if(settings.beforeOpen){settings.beforeOpen(xhr);} var params={};var body=null;var method="GET";if(post){body=objectToUrlParams(settings.data);method="POST";}else{params=settings.data||{};} xhr.open(method,addParamsToUrl(settings.url,extend({},params,currentTimestampParam())),true);if(settings.beforeSend){settings.beforeSend(xhr);} var onerror=function(){Ajax.clear(settings);try{xhr.abort();}catch(e){} settings.error(304);};if(post){if(xhr.setRequestHeader){xhr.setRequestHeader("Accept","application/json");xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");}}else{settings.timeoutId=window.setTimeout(onerror,settings.timeout+2000);} xhr.send(body);return xhr;},_clear_xhr:function(xhr){if(xhr){xhr.onreadystatechange=null;}},_clear_script:function(script){if(script){script.onerror=script.onload=script.onreadystatechange=null;if(script.parentNode){script.parentNode.removeChild(script);}}},_clear_timeout:function(settings){settings.timeoutId=clearTimer(settings.timeoutId);},_clear_jsonp:function(settings){var callbackFunctionName=settings.data.callback;if(callbackFunctionName){window[callbackFunctionName]=function(){window[callbackFunctionName]=null;};}},clear:function(settings){Ajax._clear_timeout(settings);Ajax._clear_jsonp(settings);Ajax._clear_script(document.getElementById(settings.scriptId));Ajax._clear_xhr(settings.xhr);},jsonp:function(settings){settings.timeout=settings.timeout||30000;Ajax.clear(settings);var head=document.head||document.getElementsByTagName("head")[0];var script=document.createElement("script");var startTime=getTime();var onerror=function(){Ajax.clear(settings);var endTime=getTime();settings.error(((endTime-startTime)>settings.timeout/2)?304:403);};var onload=function(){Ajax.clear(settings);settings.load();};var onsuccess=function(){settings.afterSuccess=true;settings.success.apply(null,arguments);};script.onerror=onerror;script.onload=script.onreadystatechange=function(eventLoad){if(!script.readyState||/loaded|complete/.test(script.readyState)){if(settings.afterSuccess){onload();}else{onerror();}}};if(settings.beforeOpen){settings.beforeOpen({});} if(settings.beforeSend){settings.beforeSend({});} settings.timeoutId=window.setTimeout(onerror,settings.timeout+2000);settings.scriptId=settings.scriptId||getTime();settings.afterSuccess=null;settings.data.callback=settings.scriptId+"_onmessage_"+getTime();window[settings.data.callback]=onsuccess;script.setAttribute("src",addParamsToUrl(settings.url,extend({},settings.data,currentTimestampParam())));script.setAttribute("async","async");script.setAttribute("id",settings.scriptId);head.insertBefore(script,head.firstChild);return settings;},load:function(settings){return Ajax._send(settings,false);},post:function(settings){return Ajax._send(settings,true);}};var escapeText=function(text){return(text)?window.encodeURIComponent(text):'';};var unescapeText=function(text){return(text)?window.decodeURIComponent(text):'';};Utils.parseMessage=function(messageText,keys){var msg=messageText;if(isString(messageText)){msg=Utils.parseJSON(messageText);} var message={id:msg[keys.jsonIdKey],channel:msg[keys.jsonChannelKey],text:isString(msg[keys.jsonTextKey])?unescapeText(msg[keys.jsonTextKey]):msg[keys.jsonTextKey],tag:msg[keys.jsonTagKey],time:msg[keys.jsonTimeKey],eventid:msg[keys.jsonEventIdKey]||""};return message;};var getBacktrack=function(options){return(options.backtrack)?".b"+Number(options.backtrack):"";};var getChannelsPath=function(channels,withBacktrack){var path='';for(var channelName in channels){if(!channels.hasOwnProperty||channels.hasOwnProperty(channelName)){path+="/"+channelName+(withBacktrack?getBacktrack(channels[channelName]):"");}} return path;};var getSubscriberUrl=function(pushstream,prefix,extraParams,withBacktrack){var websocket=pushstream.wrapper.type===WebSocketWrapper.TYPE;var useSSL=pushstream.useSSL;var port=normalizePort(useSSL,pushstream.port);var url=(websocket)?((useSSL)?"wss://":"ws://"):((useSSL)?"https://":"http://");url+=pushstream.host;url+=(port?(":"+port):"");url+=prefix;var channels=getChannelsPath(pushstream.channels,withBacktrack);if(pushstream.channelsByArgument){var channelParam={};channelParam[pushstream.channelsArgument]=channels.substring(1);extraParams=extend({},extraParams,channelParam);}else{url+=channels;} return addParamsToUrl(url,extraParams);};var getPublisherUrl=function(pushstream){var port=normalizePort(pushstream.useSSL,pushstream.port);var url=(pushstream.useSSL)?"https://":"http://";url+=pushstream.host;url+=(port?(":"+port):"");url+=pushstream.urlPrefixPublisher;url+="?id="+getChannelsPath(pushstream.channels,false);return url;};Utils.extract_xss_domain=function(domain){if(domain.match(/^(\d{1,3}\.){3}\d{1,3}$/)){return domain;} var domainParts=domain.split('.');var keepNumber=Math.max(domainParts.length-1,(domain.match(/(\w{4,}\.\w{2}|\.\w{3,})$/)?2:3));return domainParts.slice(-1*keepNumber).join('.');};var normalizePort=function(useSSL,port){port=Number(port||(useSSL?443:80));return((!useSSL&&port===80)||(useSSL&&port===443))?"":port;};Utils.isCrossDomainUrl=function(url){if(!url){return false;} var parser=document.createElement('a');parser.href=url;var srcPort=normalizePort(window.location.protocol==="https:",window.location.port);var dstPort=normalizePort(parser.protocol==="https:",parser.port);return(window.location.protocol!==parser.protocol)||(window.location.hostname!==parser.hostname)||(srcPort!==dstPort);};var linker=function(method,instance){return function(){return method.apply(instance,arguments);};};var clearTimer=function(timer){if(timer){window.clearTimeout(timer);} return null;};var onmessageCallback=function(event){Log4js.info("["+this.type+"] message received",arguments);var message=Utils.parseMessage(event.data,this.pushstream);if(message.tag){this.pushstream._etag=message.tag;} if(message.time){this.pushstream._lastModified=message.time;} if(message.eventid){this.pushstream._lastEventId=message.eventid;} this.pushstream._onmessage(message.text,message.id,message.channel,message.eventid,true,message.time);};var onopenCallback=function(){this.pushstream._onopen();Log4js.info("["+this.type+"] connection opened");};var onerrorCallback=function(event){Log4js.info("["+this.type+"] error (disconnected by server):",event);if((this.pushstream.readyState===PushStream.OPEN)&&(this.type===EventSourceWrapper.TYPE)&&(event.type==='error')&&(this.connection.readyState===window.EventSource.CONNECTING)){return;} this._closeCurrentConnection();this.pushstream._onerror({type:((event&&((event.type==="load")||((event.type==="close")&&(event.code===1006))))||(this.pushstream.readyState===PushStream.CONNECTING))?"load":"timeout"});};var WebSocketWrapper=function(pushstream){if(!window.WebSocket&&!window.MozWebSocket){throw "WebSocket not supported";} this.type=WebSocketWrapper.TYPE;this.pushstream=pushstream;this.connection=null;};WebSocketWrapper.TYPE="WebSocket";WebSocketWrapper.prototype={connect:function(){this._closeCurrentConnection();var params=extend({},this.pushstream.extraParams(),currentTimestampParam(),getControlParams(this.pushstream));var url=getSubscriberUrl(this.pushstream,this.pushstream.urlPrefixWebsocket,params,!this.pushstream._useControlArguments());this.connection=(window.WebSocket)?new window.WebSocket(url):new window.MozWebSocket(url);this.connection.onerror=linker(onerrorCallback,this);this.connection.onclose=linker(onerrorCallback,this);this.connection.onopen=linker(onopenCallback,this);this.connection.onmessage=linker(onmessageCallback,this);Log4js.info("[WebSocket] connecting to:",url);},disconnect:function(){if(this.connection){Log4js.debug("[WebSocket] closing connection to:",this.connection.url);this.connection.onclose=null;this._closeCurrentConnection();this.pushstream._onclose();}},_closeCurrentConnection:function(){if(this.connection){try{this.connection.close();}catch(e){} this.connection=null;}},sendMessage:function(message){if(this.connection){this.connection.send(message);}}};var EventSourceWrapper=function(pushstream){if(!window.EventSource){throw "EventSource not supported";} this.type=EventSourceWrapper.TYPE;this.pushstream=pushstream;this.connection=null;};EventSourceWrapper.TYPE="EventSource";EventSourceWrapper.prototype={connect:function(){this._closeCurrentConnection();var params=extend({},this.pushstream.extraParams(),currentTimestampParam(),getControlParams(this.pushstream));var url=getSubscriberUrl(this.pushstream,this.pushstream.urlPrefixEventsource,params,!this.pushstream._useControlArguments());this.connection=new window.EventSource(url);this.connection.onerror=linker(onerrorCallback,this);this.connection.onopen=linker(onopenCallback,this);this.connection.onmessage=linker(onmessageCallback,this);Log4js.info("[EventSource] connecting to:",url);},disconnect:function(){if(this.connection){Log4js.debug("[EventSource] closing connection to:",this.connection.url);this.connection.onclose=null;this._closeCurrentConnection();this.pushstream._onclose();}},_closeCurrentConnection:function(){if(this.connection){try{this.connection.close();}catch(e){} this.connection=null;}}};var StreamWrapper=function(pushstream){this.type=StreamWrapper.TYPE;this.pushstream=pushstream;this.connection=null;this.url=null;this.frameloadtimer=null;this.pingtimer=null;this.iframeId="PushStreamManager_"+pushstream.id;};StreamWrapper.TYPE="Stream";StreamWrapper.prototype={connect:function(){this._closeCurrentConnection();var domain=Utils.extract_xss_domain(this.pushstream.host);try{document.domain=domain;}catch(e){Log4js.error("[Stream] (warning) problem setting document.domain = "+domain+" (OBS: IE8 does not support set IP numbers as domain)");} var params=extend({},this.pushstream.extraParams(),currentTimestampParam(),{"streamid":this.pushstream.id},getControlParams(this.pushstream));this.url=getSubscriberUrl(this.pushstream,this.pushstream.urlPrefixStream,params,!this.pushstream._useControlArguments());Log4js.debug("[Stream] connecting to:",this.url);this.loadFrame(this.url);},disconnect:function(){if(this.connection){Log4js.debug("[Stream] closing connection to:",this.url);this._closeCurrentConnection();this.pushstream._onclose();}},_clear_iframe:function(){var oldIframe=document.getElementById(this.iframeId);if(oldIframe){oldIframe.onload=null;oldIframe.src="about:blank";if(oldIframe.parentNode){oldIframe.parentNode.removeChild(oldIframe);}}},_closeCurrentConnection:function(){this._clear_iframe();if(this.connection){this.pingtimer=clearTimer(this.pingtimer);this.frameloadtimer=clearTimer(this.frameloadtimer);this.connection=null;this.transferDoc=null;if(typeof window.CollectGarbage==='function'){window.CollectGarbage();}}},loadFrame:function(url){this._clear_iframe();var ifr=null;if("ActiveXObject"in window){var transferDoc=new window.ActiveXObject("htmlfile");transferDoc.open();transferDoc.write("\x3C"+"html"+"\x3E\x3C"+"script"+"\x3E"+"document.domain='"+document.domain+"';\x3C"+"/script"+"\x3E");transferDoc.write("\x3C"+"body"+"\x3E\x3C"+"iframe id='"+this.iframeId+"' src='"+url+"'\x3E\x3C"+"/iframe"+"\x3E\x3C"+"/body"+"\x3E\x3C"+"/html"+"\x3E");transferDoc.parentWindow.PushStream=PushStream;transferDoc.close();ifr=transferDoc.getElementById(this.iframeId);this.transferDoc=transferDoc;}else{ifr=document.createElement("IFRAME");ifr.style.width="1px";ifr.style.height="1px";ifr.style.border="none";ifr.style.position="absolute";ifr.style.top="-10px";ifr.style.marginTop="-10px";ifr.style.zIndex="-20";ifr.PushStream=PushStream;document.body.appendChild(ifr);ifr.setAttribute("src",url);ifr.setAttribute("id",this.iframeId);} ifr.onload=linker(onerrorCallback,this);this.connection=ifr;this.frameloadtimer=window.setTimeout(linker(onerrorCallback,this),this.pushstream.timeout);},register:function(iframeWindow){this.frameloadtimer=clearTimer(this.frameloadtimer);iframeWindow.p=linker(this.process,this);this.connection.onload=linker(this._onframeloaded,this);this.pushstream._onopen();this.setPingTimer();Log4js.info("[Stream] frame registered");},process:function(id,channel,text,eventid,time,tag){this.pingtimer=clearTimer(this.pingtimer);Log4js.info("[Stream] message received",arguments);if(id!==-1){if(tag){this.pushstream._etag=tag;} if(time){this.pushstream._lastModified=time;} if(eventid){this.pushstream._lastEventId=eventid;}} this.pushstream._onmessage(unescapeText(text),id,channel,eventid||"",true,time);this.setPingTimer();},_onframeloaded:function(){Log4js.info("[Stream] frame loaded (disconnected by server)");this.pushstream._onerror({type:"timeout"});this.connection.onload=null;this.disconnect();},setPingTimer:function(){if(this.pingtimer){clearTimer(this.pingtimer);} this.pingtimer=window.setTimeout(linker(onerrorCallback,this),this.pushstream.pingtimeout);}};var LongPollingWrapper=function(pushstream){this.type=LongPollingWrapper.TYPE;this.pushstream=pushstream;this.connection=null;this.opentimer=null;this.messagesQueue=[];this._linkedInternalListen=linker(this._internalListen,this);this.xhrSettings={timeout:this.pushstream.timeout,data:{},url:null,success:linker(this.onmessage,this),error:linker(this.onerror,this),load:linker(this.onload,this),beforeSend:linker(this.beforeSend,this),afterReceive:linker(this.afterReceive,this)};};LongPollingWrapper.TYPE="LongPolling";LongPollingWrapper.prototype={connect:function(){this.messagesQueue=[];this._closeCurrentConnection();this.urlWithBacktrack=getSubscriberUrl(this.pushstream,this.pushstream.urlPrefixLongpolling,{},true);this.urlWithoutBacktrack=getSubscriberUrl(this.pushstream,this.pushstream.urlPrefixLongpolling,{},false);this.xhrSettings.url=this.urlWithBacktrack;this.useJSONP=this.pushstream._crossDomain||this.pushstream.useJSONP;this.xhrSettings.scriptId="PushStreamManager_"+this.pushstream.id;if(this.useJSONP){this.pushstream.messagesControlByArgument=true;} this._listen();this.opentimer=window.setTimeout(linker(onopenCallback,this),150);Log4js.info("[LongPolling] connecting to:",this.xhrSettings.url);},_listen:function(){if(this._internalListenTimeout){clearTimer(this._internalListenTimeout);} this._internalListenTimeout=window.setTimeout(this._linkedInternalListen,100);},_internalListen:function(){if(this.pushstream._keepConnected){this.xhrSettings.url=this.pushstream._useControlArguments()?this.urlWithoutBacktrack:this.urlWithBacktrack;this.xhrSettings.data=extend({},this.pushstream.extraParams(),this.xhrSettings.data,getControlParams(this.pushstream));if(this.useJSONP){this.connection=Ajax.jsonp(this.xhrSettings);}else if(!this.connection){this.connection=Ajax.load(this.xhrSettings);}}},disconnect:function(){if(this.connection){Log4js.debug("[LongPolling] closing connection to:",this.xhrSettings.url);this._closeCurrentConnection();this.pushstream._onclose();}},_closeCurrentConnection:function(){this.opentimer=clearTimer(this.opentimer);if(this.connection){try{this.connection.abort();}catch(e){try{Ajax.clear(this.connection);}catch(e1){}} this.connection=null;this.xhrSettings.url=null;}},beforeSend:function(xhr){if(!this.pushstream.messagesControlByArgument){xhr.setRequestHeader("If-None-Match",this.pushstream._etag);xhr.setRequestHeader("If-Modified-Since",this.pushstream._lastModified);}},afterReceive:function(xhr){if(!this.pushstream.messagesControlByArgument){this.pushstream._etag=xhr.getResponseHeader('Etag');this.pushstream._lastModified=xhr.getResponseHeader('Last-Modified');} this.connection=null;},onerror:function(status){this._closeCurrentConnection();if(this.pushstream._keepConnected){if(status===304){this._listen();}else{Log4js.info("[LongPolling] error (disconnected by server):",status);this.pushstream._onerror({type:((status===403)||(this.pushstream.readyState===PushStream.CONNECTING))?"load":"timeout"});}}},onload:function(){this._listen();},onmessage:function(responseText){if(this._internalListenTimeout){clearTimer(this._internalListenTimeout);} Log4js.info("[LongPolling] message received",responseText);var lastMessage=null;var messages=isArray(responseText)?responseText:responseText.replace(/\}\{/g,"}\r\n{").split("\r\n");for(var i=0;i0){var message=this.messagesQueue.shift();this.pushstream._onmessage(message.text,message.id,message.channel,message.eventid,(this.messagesQueue.length===0),message.time);}}};var PushStreamManager=[];var PushStream=function(settings){settings=settings||{};this.id=PushStreamManager.push(this)-1;this.useSSL=settings.useSSL||false;this.host=settings.host||window.location.hostname;this.port=Number(settings.port||(this.useSSL?443:80));this.timeout=settings.timeout||30000;this.pingtimeout=settings.pingtimeout||30000;this.reconnectOnTimeoutInterval=settings.reconnectOnTimeoutInterval||3000;this.reconnectOnChannelUnavailableInterval=settings.reconnectOnChannelUnavailableInterval||60000;this.autoReconnect=(settings.autoReconnect!==false);this.lastEventId=settings.lastEventId||null;this.messagesPublishedAfter=settings.messagesPublishedAfter;this.messagesControlByArgument=settings.messagesControlByArgument||false;this.tagArgument=settings.tagArgument||'tag';this.timeArgument=settings.timeArgument||'time';this.eventIdArgument=settings.eventIdArgument||'eventid';this.useJSONP=settings.useJSONP||false;this._reconnecttimer=null;this._etag=0;this._lastModified=null;this._lastEventId=null;this.urlPrefixPublisher=settings.urlPrefixPublisher||'/pub';this.urlPrefixStream=settings.urlPrefixStream||'/sub';this.urlPrefixEventsource=settings.urlPrefixEventsource||'/ev';this.urlPrefixLongpolling=settings.urlPrefixLongpolling||'/lp';this.urlPrefixWebsocket=settings.urlPrefixWebsocket||'/ws';this.jsonIdKey=settings.jsonIdKey||'id';this.jsonChannelKey=settings.jsonChannelKey||'channel';this.jsonTextKey=settings.jsonTextKey||'text';this.jsonTagKey=settings.jsonTagKey||'tag';this.jsonTimeKey=settings.jsonTimeKey||'time';this.jsonEventIdKey=settings.jsonEventIdKey||'eventid';this.modes=(settings.modes||'eventsource|websocket|stream|longpolling').split('|');this.wrappers=[];this.wrapper=null;this.onchanneldeleted=settings.onchanneldeleted||null;this.onmessage=settings.onmessage||null;this.onerror=settings.onerror||null;this.onstatuschange=settings.onstatuschange||null;this.extraParams=settings.extraParams||function(){return{};};this.channels={};this.channelsCount=0;this.channelsByArgument=settings.channelsByArgument||false;this.channelsArgument=settings.channelsArgument||'channels';this._crossDomain=Utils.isCrossDomainUrl(getPublisherUrl(this));for(var i=0;i0){date=new Date();date.setTime(date.getTime()-(messagesPublishedAfter*1000));}else if(messagesPublishedAfter<0){date=new Date(0);}} if(isDate(date)){this._lastModified=Utils.dateToUTCString(date);}} this._disconnect();this._setState(PushStream.CONNECTING);this.wrapper=this.wrappers[this._lastUsedMode++%this.wrappers.length];try{this.wrapper.connect();}catch(e){if(this.wrapper){this.wrapper.disconnect();}}},_disconnect:function(){this._reconnecttimer=clearTimer(this._reconnecttimer);if(this.wrapper){this.wrapper.disconnect();}},_onopen:function(){this._reconnecttimer=clearTimer(this._reconnecttimer);this._setState(PushStream.OPEN);if(this._lastUsedMode>0){this._lastUsedMode--;}},_onclose:function(){this._reconnecttimer=clearTimer(this._reconnecttimer);this._setState(PushStream.CLOSED);this._reconnect(this.reconnectOnTimeoutInterval);},_onmessage:function(text,id,channel,eventid,isLastMessageFromBatch,time){Log4js.debug("message",text,id,channel,eventid,isLastMessageFromBatch,time);if(id===-2){if(this.onchanneldeleted){this.onchanneldeleted(channel);}}else if(id>0){if(this.onmessage){this.onmessage(text,id,channel,eventid,isLastMessageFromBatch,time);}}},_onerror:function(error){this._setState(PushStream.CLOSED);this._reconnect((error.type==="timeout")?this.reconnectOnTimeoutInterval:this.reconnectOnChannelUnavailableInterval);if(this.onerror){this.onerror(error);}},_reconnect:function(timeout){if(this.autoReconnect&&this._keepConnected&&!this._reconnecttimer&&(this.readyState!==PushStream.CONNECTING)){Log4js.info("trying to reconnect in",timeout);this._reconnecttimer=window.setTimeout(linker(this._connect,this),timeout);}},sendMessage:function(message,successCallback,errorCallback){message=escapeText(message);if(this.wrapper.type===WebSocketWrapper.TYPE){this.wrapper.sendMessage(message);if(successCallback){successCallback();}}else{Ajax.post({url:getPublisherUrl(this),data:message,success:successCallback,error:errorCallback,crossDomain:this._crossDomain});}}};PushStream.sendMessage=function(url,message,successCallback,errorCallback){Ajax.post({url:url,data:escapeText(message),success:successCallback,error:errorCallback});};PushStream.register=function(iframe){var matcher=iframe.window.location.href.match(/streamid=([0-9]*)&?/);if(matcher[1]&&PushStreamManager[matcher[1]]){PushStreamManager[matcher[1]].wrapper.register(iframe);}};PushStream.unload=function(){for(var i=0;i